/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2025-01-21 16:09:28
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 13:06:07
 * @FilePath     : \openchaoji-corelib\x86\evcc\hal_compile_evcc_x86.c
 * @Description  :
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "../include/OpenChaoJi_evcc.h"

#include "../app_hal_x86.h"
#include "evcc_x86.h"

struct evcc_hal_battery
{
    // 配置部分
    uint32_t capacity_max;      // 总容量(Wh) 0%-100%
    uint32_t voltage_max;       // 最大电压(0.1V) 100%
    uint32_t voltage_min;       // 最小电压(0.1V) 0%
    uint32_t power_max;         // 最大充电功率(0.01kW)

    uint32_t soc_start;         // 开始充电SOC(0.1%)
    uint32_t soc_stop;          // 停止充电SOC(0.1%)

    // 运行部分
    bool start;                 // 是否投入充电

    uint32_t energy;            // 当前电池电量(Wh)
    uint32_t soc;               // 当前SOC(0.1%)
    uint32_t last_ticks;        // 积分检查时间戳
};

struct evcc_hal_Info
{
    int idx;

    int socket_evcc;
    struct sockaddr_in dest_addr_secc;
    fifo_queue recv_queue;

    // 导引控制相关继电器, 需要同步给secc
    struct can_data_pilot_sync pilot_sync_status;
    uint32_t sync_send_ticks;

    struct hal_x86_relay relay_plug;
    struct hal_x86_relay relay_pe_lost; // PE断开模拟

    struct hal_x86_relay relay_S;

    struct hal_x86_relay relay_S2;
    struct hal_x86_relay relay_S2p;
    struct hal_x86_relay relay_Sv;

    // 非导引同步相关继电器
    struct hal_x86_relay relay_dc;
    struct hal_x86_relay relay_lock;
    struct hal_x86_relay relay_emergency;

    // 电池
    struct evcc_hal_battery battery;
};

static struct evcc_hal_Info s_hal_info_evcc[2];

uint16_t evcc_hal_battery_get_voltage(struct evcc_hal_battery * battery)
{
    uint32_t vol = battery->soc * (battery->voltage_max - battery->voltage_min) / 1000 + battery->voltage_min;

    return vol;
}

static void evcc_hal_battery_reset(struct evcc_hal_battery *battery)
{
    LOG_PILOT_HAL("HAL Battery Reset");
    battery->start = false;
    battery->last_ticks = 0;

    battery->soc = battery->soc_start;
    battery->energy = battery->capacity_max * battery->soc / 1000;
}

static void evcc_hal_battery_start(struct evcc_hal_battery *battery)
{
    if (!battery->start)
    {
        LOG_PILOT_HAL("Battery start");

        evcc_hal_battery_reset(battery);

        battery->start = true;
        battery->last_ticks = OpenChaoJi_os_get_ticks();
    }
}

void evcc_hal_one_reset(int idx)
{
    LOG_PILOT_HAL("HAL Relay Reset");

    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_pe_lost, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_S, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_S2, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_S2p, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_Sv, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_dc, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_lock, 0);
    hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_emergency, 0);

    evcc_hal_battery_reset(&s_hal_info_evcc[idx].battery);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_battery_voltage = evcc_hal_battery_get_voltage(&s_hal_info_evcc[idx].battery);

    return;
}

void evcc_hal_one_init(int idx)
{
    memset(&s_hal_info_evcc[idx], 0x00, sizeof(struct evcc_hal_Info));

    s_hal_info_evcc[idx].idx = idx;

    // 初始化SECC与EVCC通信的socket
    s_hal_info_evcc[idx].socket_evcc = hal_create_udp_socket(HAL_UDP_PORT_EVCC_START + idx);
    hal_init_dest_socket_addr(HAL_UDP_ADDR_SECC, HAL_UDP_PORT_SECC_START + idx, &s_hal_info_evcc[idx].dest_addr_secc);
    fifo_init(&s_hal_info_evcc[idx].recv_queue);

    // 初始化导引同步相关继电器
    if (idx == 0)
    {
        s_hal_info_evcc[idx].pilot_sync_status.pilot_type = HA_SIMU_PILOT_A_A;
    }
    else if (idx == 1)
    {
        s_hal_info_evcc[idx].pilot_sync_status.pilot_type = HA_SIMU_PILOT_B_B;
    }
    else if (idx == 2)
    {
        s_hal_info_evcc[idx].pilot_sync_status.pilot_type = HA_SIMU_PILOT_B_A;
    }

    // plug初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_plug, "plug", 500, 500, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_plug = 0;

    // pe断开初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_pe_lost, "pe_lost", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_pe_lost = 0;

    // S初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_S, "S", 200, 200, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_S = 0;

    // S2初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_S2, "s2", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_S2 = 0;

    // S2p初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_S2p, "s2p", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_S2p = 0;

    // Sv初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_Sv, "sv", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_Sv = 0;

    // dc初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_dc, "dc", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_dc = 0;

    // lock初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_lock, "lock", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_lock = 0;

    // emergency初始状态断开
    hal_x86_relay_init(&s_hal_info_evcc[idx].relay_emergency, "emergency", 10, 10, 0);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_emergency = 0;

    // 初始化电池信息
    s_hal_info_evcc[idx].battery.capacity_max = 4000;     // 100kWh
    s_hal_info_evcc[idx].battery.voltage_max = 7500;        // 750V
    s_hal_info_evcc[idx].battery.voltage_min = 6500;        // 650V
    s_hal_info_evcc[idx].battery.power_max = 40000;         // 400kW
    s_hal_info_evcc[idx].battery.soc_start = 200;           // 20%
    s_hal_info_evcc[idx].battery.soc_stop = 900;            // 90%

    evcc_hal_battery_reset(&s_hal_info_evcc[idx].battery);
    s_hal_info_evcc[idx].pilot_sync_status.evcc_battery_voltage = evcc_hal_battery_get_voltage(&s_hal_info_evcc[idx].battery);

    return;
}

void evcc_hal_one_term(int idx)
{
    close(s_hal_info_evcc[idx].socket_evcc);
}

OpenChaoJi_hal_handle evcc_hal_one_handle(int idx)
{
    if ((idx >= 0) && (idx < HAL_SIMU_CONNECTOR_NUM))
    {
        return (OpenChaoJi_hal_handle)(&s_hal_info_evcc[idx]);
    }

    return NULL;
}

static struct evcc_hal_Info * evcc_hal_handle2info(OpenChaoJi_hal_handle hal_handle)
{
    for (int idx = 0; idx < HAL_SIMU_CONNECTOR_NUM; idx++)
    {
        if (evcc_hal_one_handle(idx) == hal_handle)
        {
            return &s_hal_info_evcc[idx];
        }
    }

    return NULL;
}

// 更新继电器状态字节, 如果变化则发送给secc
static bool evcc_hal_x86_relay_sync(struct evcc_hal_Info * info)
{
    uint8_t plug = hal_x86_relay_get(info->idx, &info->relay_plug);
    uint8_t pe_lost = hal_x86_relay_get(info->idx, &info->relay_pe_lost);
    uint8_t S = hal_x86_relay_get(info->idx, &info->relay_S);
    uint8_t S2 = hal_x86_relay_get(info->idx, &info->relay_S2);
    uint8_t S2p = hal_x86_relay_get(info->idx, &info->relay_S2p);
    uint8_t Sv = hal_x86_relay_get(info->idx, &info->relay_Sv);
    uint8_t dc = hal_x86_relay_get(info->idx, &info->relay_dc);
    uint8_t lock = hal_x86_relay_get(info->idx, &info->relay_lock);
    uint8_t emergency = hal_x86_relay_get(info->idx, &info->relay_emergency);

    bool changed = false;
    if (plug != info->pilot_sync_status.evcc_plug)
    {
        LOG_PILOT_HAL("[%d]evcc_plug: %d -> %d", info->idx, info->pilot_sync_status.evcc_plug, plug);
        info->pilot_sync_status.evcc_plug = plug;
        changed = true;
    }
    if (pe_lost != info->pilot_sync_status.evcc_pe_lost)
    {
        LOG_PILOT_HAL("[%d]evcc_pe_lost: %d -> %d", info->idx, info->pilot_sync_status.evcc_pe_lost, pe_lost);
        info->pilot_sync_status.evcc_pe_lost = pe_lost;
        changed = true;
    }
    if (S != info->pilot_sync_status.evcc_S)
    {
        LOG_PILOT_HAL("[%d]evcc_S: %d -> %d", info->idx, info->pilot_sync_status.evcc_S, S);
        info->pilot_sync_status.evcc_S = S;
        changed = true;
    }
    if (S2 != info->pilot_sync_status.evcc_S2)
    {
        LOG_PILOT_HAL("[%d]evcc_S2: %d -> %d", info->idx, info->pilot_sync_status.evcc_S2, S2);
        info->pilot_sync_status.evcc_S2 = S2;
        changed = true;
    }
    if (S2p != info->pilot_sync_status.evcc_S2p)
    {
        LOG_PILOT_HAL("[%d]evcc_S2p: %d -> %d", info->idx, info->pilot_sync_status.evcc_S2p, S2p);
        info->pilot_sync_status.evcc_S2p = S2p;
        changed = true;
    }
    if (Sv != info->pilot_sync_status.evcc_Sv)
    {
        LOG_PILOT_HAL("[%d]evcc_Sv: %d -> %d", info->idx, info->pilot_sync_status.evcc_Sv, Sv);
        info->pilot_sync_status.evcc_Sv = Sv;
        changed = true;
    }
    if (dc != info->pilot_sync_status.evcc_dc)
    {
        LOG_PILOT_HAL("[%d]evcc_dc: %d -> %d", info->idx, info->pilot_sync_status.evcc_dc, dc);
        info->pilot_sync_status.evcc_dc = dc;
        changed = true;
    }
    if (info->pilot_sync_status.evcc_lock != lock)
    {
        LOG_PILOT_HAL("[%d]evcc_lock: %d -> %d", info->idx, info->pilot_sync_status.evcc_lock, lock);
        info->pilot_sync_status.evcc_lock = lock;
        changed = true;
    }
    if (info->pilot_sync_status.evcc_emergency != emergency)
    {
        LOG_PILOT_HAL("[%d]evcc_emergency: %d -> %d", info->idx, info->pilot_sync_status.evcc_emergency, emergency);
        info->pilot_sync_status.evcc_emergency = emergency;
        changed = true;
    }

    return changed;
}

static uint32_t evcc_hal_battery_get_power(struct evcc_hal_Info * info)
{
    uint32_t power = 0;

    if (info->battery.start)
    {
        // 电池投入, 需要检查C1C2/C5C6 是否闭合
        if (info->pilot_sync_status.evcc_dc && info->pilot_sync_status.secc_dc)
        {
            power = info->pilot_sync_status.secc_output_power;
        }

        // 不能超过额定输入功率
        if (power > info->battery.power_max)
        {
            power = info->battery.power_max;
        }
    }

    return power;
}

static bool evcc_hal_battery_service(struct evcc_hal_Info * info)
{
    uint32_t soc = info->battery.soc;

    if (info->battery.start)       // 电池未投入
    {
        soc = info->battery.soc;

        uint32_t ticks = OpenChaoJi_os_get_ticks();
        uint32_t power = evcc_hal_battery_get_power(info);
        if (power > 0)
        {
            uint32_t delta = ticks - info->battery.last_ticks;  // ms
            uint32_t delta_energy = power * delta * 10 / 1000 / 3600; // 0.01kW.ms * 10 -> W.ms / 1000 / 3600 -> Wh

            info->battery.energy += delta_energy;

            soc = info->battery.energy * 1000 / info->battery.capacity_max;

            if (soc >= info->battery.soc_stop)
            {
                LOG_PILOT_HAL("[%d] SoC reached %d", info->idx, soc);
                info->battery.start = false;
            }
        }

        info->battery.last_ticks = ticks;
    }

    if (soc != info->battery.soc)
    {
        LOG_DATA_HAL("[%d]battery_soc: %d -> %d secc_power=%d", info->idx, info->battery.soc, soc, info->pilot_sync_status.secc_output_power);
        info->battery.soc = soc;
        return true;
    }

    return false;
}

uint16_t evcc_hal_one_get_battery_request_voltage(int idx)
{
    return evcc_hal_battery_get_voltage(&s_hal_info_evcc[idx].battery) + 50;    // 当前电池电压+5V
}

uint16_t evcc_hal_one_get_battery_request_current(int idx)
{
    int current = s_hal_info_evcc[idx].battery.power_max * 1000 / evcc_hal_one_get_battery_request_voltage(idx); // 0.01kW / 0.1V
    if (idx == 0 && current > 4000)
        current = 4000;
    return (uint16_t)current;
}

bool evcc_hal_one_get_battery_soc_reached(int idx)
{
    if ((s_hal_info_evcc[idx].battery.soc >= s_hal_info_evcc[idx].battery.soc_start)
        && (s_hal_info_evcc[idx].battery.soc >= s_hal_info_evcc[idx].battery.soc_stop)
    )
    {
        return true;
    }

    return false;
}

void evcc_hal_one_service(int idx)
{
    if (idx >= 0 && idx < HAL_SIMU_CONNECTOR_NUM)
    {
        // 先刷新各个继电器状态(可能的命令行直接强制修改)
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_plug);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_pe_lost);

        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_S);

        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_S2);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_S2p);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_Sv);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_dc);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_lock);
        hal_x86_relay_service(idx, &s_hal_info_evcc[idx].relay_emergency);

        // 更新继电器状态字节, 如果变化则发送给secc;
        bool relay_changed = evcc_hal_x86_relay_sync(&s_hal_info_evcc[idx]);

        evcc_hal_battery_service(&s_hal_info_evcc[idx]);

        bool vol_changed = false;
        uint16_t vol = evcc_hal_battery_get_voltage(&s_hal_info_evcc[idx].battery);
        if (vol != s_hal_info_evcc[idx].pilot_sync_status.evcc_battery_voltage)
        {
            LOG_DATA_HAL("[%d]battery_voltage: %d->%d", idx, s_hal_info_evcc[idx].pilot_sync_status.evcc_battery_voltage, vol);
            s_hal_info_evcc[idx].pilot_sync_status.evcc_battery_voltage = vol;
            vol_changed = true;
        }

        if (relay_changed || vol_changed || (OpenChaoJi_os_get_ticks() > s_hal_info_evcc[idx].sync_send_ticks + 1000))
        {
            struct can_pdu can_send_info;
            can_send_info.can_id.uint32_tWord = CAN_ID_PILOT_SYNC;
            can_send_info.can_dlc = 8;
            memcpy(can_send_info.data, &s_hal_info_evcc[idx].pilot_sync_status, 8);

            if (relay_changed)
            {
                LOG_PILOT_HAL("[%d]pilot->secc", idx);
                hal_log_pilot_sync(&s_hal_info_evcc[idx].pilot_sync_status);
            }

            OpenChaoJi_evcc_hal_information_send_can_voluation(evcc_hal_one_handle(idx), &can_send_info);
            s_hal_info_evcc[idx].sync_send_ticks = OpenChaoJi_os_get_ticks();
        }
    }
}

void evcc_hal_one_plug(int idx, int close)
{
    if ((idx >= 0) && (idx < HAL_SIMU_CONNECTOR_NUM))
    {
        hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_plug, close);
        hal_x86_relay_set(idx, &s_hal_info_evcc[idx].relay_S, close);

        evcc_hal_one_service(idx);
    }
}

/**
EVCC 相关接口
*/

/*******************************CAN通信接口*******************************/

/**
 * @brief  CAN接收
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  can_info_type: can消息结构体
 * @return 0:OK 接收成功 -1:ERR 接受失败
 */
void evcc_hal_can_data_pilot_sync_func(OpenChaoJi_hal_handle handle, struct can_pdu * can_recv_info)
{
    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    struct can_data_pilot_sync sync;
    memcpy(&sync, can_recv_info->data, 8);

    bool changed = false;
    // evcc只更新secc的开关变化状态, 自身的开关状态从relay获取
    if (info->pilot_sync_status.secc_pe_lost != sync.secc_pe_lost)
    {
        LOG_PILOT_HAL("secc_pe_lost: %d -> %d", info->pilot_sync_status.secc_pe_lost, sync.secc_pe_lost);
        info->pilot_sync_status.secc_pe_lost = sync.secc_pe_lost;
        changed = true;
    }
    if (info->pilot_sync_status.secc_S0 != sync.secc_S0)
    {
        LOG_PILOT_HAL("secc_S0: %d -> %d", info->pilot_sync_status.secc_S0, sync.secc_S0);
        info->pilot_sync_status.secc_S0 = sync.secc_S0;
        changed = true;
    }
    if (info->pilot_sync_status.secc_S1 != sync.secc_S1)
    {
        LOG_PILOT_HAL("secc_S1: %d -> %d", info->pilot_sync_status.secc_S1, sync.secc_S1);
        info->pilot_sync_status.secc_S1 = sync.secc_S1;
        changed = true;
    }
    if (info->pilot_sync_status.secc_dc != sync.secc_dc)
    {
        LOG_PILOT_HAL("secc_dc: %d -> %d", info->pilot_sync_status.secc_dc, sync.secc_dc);
        info->pilot_sync_status.secc_dc = sync.secc_dc;
        changed = true;
    }
    if (info->pilot_sync_status.secc_ac != sync.secc_ac)
    {
        LOG_PILOT_HAL("secc_ac: %d -> %d", info->pilot_sync_status.secc_ac, sync.secc_ac);
        info->pilot_sync_status.secc_ac = sync.secc_ac;
        changed = true;
    }
    if (info->pilot_sync_status.secc_aux != sync.secc_aux)
    {
        LOG_PILOT_HAL("secc_aux: %d -> %d", info->pilot_sync_status.secc_aux, sync.secc_aux);
        info->pilot_sync_status.secc_aux = sync.secc_aux;
        changed = true;
    }
    if (info->pilot_sync_status.secc_lock != sync.secc_lock)
    {
        LOG_PILOT_HAL("secc_lock: %d -> %d", info->pilot_sync_status.secc_lock, sync.secc_lock);
        info->pilot_sync_status.secc_lock = sync.secc_lock;
        changed = true;
    }
    if (info->pilot_sync_status.secc_emergency != sync.secc_emergency)
    {
        LOG_PILOT_HAL("secc_emergency: %d -> %d", info->pilot_sync_status.secc_emergency, sync.secc_emergency);
        info->pilot_sync_status.secc_emergency = sync.secc_emergency;
        changed = true;
    }
    if (info->pilot_sync_status.secc_output_power != sync.secc_output_power)
    {
        LOG_PILOT_HAL("secc_output_power: %d -> %d", info->pilot_sync_status.secc_output_power, sync.secc_output_power);
        info->pilot_sync_status.secc_output_power = sync.secc_output_power;
        // changed = true;
    }
    if (changed)
    {
        LOG_PILOT_HAL("[%d]pilot<-secc", info->idx);
        hal_log_pilot_sync(&sync);
    }

    return;
}
int OpenChaoJi_evcc_hal_information_recv_can_voluation(OpenChaoJi_hal_handle handle, struct can_pdu * can_recv_info)
{
    HAL_DEBUG_LINE
    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return -1;
    }

    return hal_try_read_can_pdu(handle, info->socket_evcc, &info->recv_queue, evcc_hal_can_data_pilot_sync_func, can_recv_info);
}

/**
 * @brief  CAN发送
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  can_info_type: can消息结构体
 * @return 0:OK 发送成功 -1:ERR 发送失败
 */
int OpenChaoJi_evcc_hal_information_send_can_voluation(OpenChaoJi_hal_handle handle, const struct can_pdu * can_send_info)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return -1;
    }

    return hal_send_can_pdu(handle, info->socket_evcc, &info->dest_addr_secc, can_send_info);
}

/******************************控制继电器及反馈******************************/

/**
 * @brief  控制直流接触器
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  ctl: 0-断开 1-闭合
 * @return void
 * @remark C5\C6
 */
void OpenChaoJi_evcc_hal_gbt_close_dc_relay(OpenChaoJi_hal_handle handle,unsigned char ctl)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    hal_x86_relay_set(info->idx, &info->relay_dc, ctl);
    evcc_hal_one_service(info->idx);

    return;
}

/**
 * @brief  控制电子锁锁止
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  ctl: 0-断开 1-闭合
 * @return void
 */
void OpenChaoJi_evcc_hal_gbt_b_lock(OpenChaoJi_hal_handle handle,unsigned char ctl)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    hal_x86_relay_set(info->idx, &info->relay_lock, ctl);
    evcc_hal_one_service(info->idx);

    return;
}

/**
 * @brief  控制S2
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  ctl: 0-断开 1-闭合
 * @return void
 */
void OpenChaoJi_evcc_hal_gbt_b_close_s2(OpenChaoJi_hal_handle handle,unsigned char ctl)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    hal_x86_relay_set(info->idx, &info->relay_S2, ctl);
    evcc_hal_one_service(info->idx);

    return;
}

/**
 * @brief  控制S2p
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  ctl: 0-断开 1-闭合
 * @return void
 */
void OpenChaoJi_evcc_hal_gbt_b_close_s2p(OpenChaoJi_hal_handle handle,unsigned char ctl)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    hal_x86_relay_set(info->idx, &info->relay_S2p, ctl);
    evcc_hal_one_service(info->idx);

    return;
}

/**
 * @brief  控制Sv
 * @param  OpenChaoJi_hal_handle: 句柄
 * @param  ctl: 0-断开 1-闭合
 * @return void
 */
void OpenChaoJi_evcc_hal_gbt_b_close_sv(OpenChaoJi_hal_handle handle,unsigned char ctl)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    hal_x86_relay_set(info->idx, &info->relay_Sv, ctl);
    evcc_hal_one_service(info->idx);

    return;
}

/**
 * @brief  获取直流接触器状态
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return     C5   C6
 *         0   断   断
 *         1   断   通
 *         2   通   断
 *         3   通   通
 * @remark C5\C6
 */
unsigned char OpenChaoJi_evcc_hal_get_status_dc_relay(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    if (hal_x86_relay_get(info->idx, &info->relay_dc) == 1)
    {
        return 3;
    }

    return 0;
}

/**
 * @brief  获取电子锁锁止
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 0-断开 1-闭合
 */
bool OpenChaoJi_evcc_hal_gbt_b_is_locked(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return false;
    }

    return hal_x86_relay_get(info->idx, &info->relay_lock);
}

/**
 * @brief  获取S2状态
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 0-断开 1-闭合
 */
bool OpenChaoJi_evcc_hal_gbt_b_is_closed_s2(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return false;
    }

    return hal_x86_relay_get(info->idx, &info->relay_S2);
}

/**
 * @brief  获取S2p状态
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 0-断开 1-闭合
 */
bool OpenChaoJi_evcc_hal_gbt_b_is_closed_s2p(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return false;
    }

    return hal_x86_relay_get(info->idx, &info->relay_S2p);
}

/**
 * @brief  获取Sv状态
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 0-断开 1-闭合
 */
bool OpenChaoJi_evcc_hal_gbt_b_is_closed_sv(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return hal_x86_relay_get(info->idx, &info->relay_Sv);
}

/**
 * @brief  获取检测点2电压
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 检测点2电压
 * @remark 返回检测点2的检测电压值
 */
int OpenChaoJi_evcc_hal_gbt_get_vol_checkpoint_2(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    float voltage = hal_pilot_voltage_evcc_checkpoint_2(&info->pilot_sync_status);
    return (int)(voltage * 100.0);
}

/**
 * @brief  获取检测点3电压
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 检测点3电压
 * @remark 返回检测点3的检测电压值
 */
int OpenChaoJi_evcc_hal_gbt_b_get_vol_checkpoint_3(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    float voltage = hal_pilot_voltage_evcc_checkpoint_3(&info->pilot_sync_status);
    return (int)(voltage * 100.0);
}

bool OpenChaoJi_evcc_hal_is_emergency_pushed(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return hal_x86_relay_get(info->idx, &info->relay_emergency);
}


/**
 * @brief  (A类系统)获取桩端辅助接口连接状态
 * @param  OpenChaoJi_hal_handle: 句柄
 * @return 桩端辅助接口连接状态
 */
bool OpenChaoJi_evcc_hal_gbt_a_is_secc_aux_connected(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->pilot_sync_status.secc_aux;
}

/****** 此头文件嘉盛和长园共同维护, 为了避免合并冲突, 嘉盛仅修改本行以上部分, 长园只修改本行以下部分 ******/

#if 0
/*
 * 功能  启动阶段-自检启动接口
 * 参数  context: 句柄
 * 参数  voltage: 绝缘电压值
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_selfcheck_request_start(OpenChaoJi_hal_handle hal_handle, float voltage)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  启动阶段-自检停止接口
 * 参数  context: 句柄
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_selfcheck_request_stop(OpenChaoJi_hal_handle hal_handle)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  启动阶段-自检结果获取
 * 参数  context: 句柄
 * 参数  rp_value: 正对地阻值存储地址
 * 参数  rn_value: 负对地阻值存储地址
 * 返回  粘连/短路/绝缘 自检状态和结果
 */
struct OpenChaoJi_evcc_hal_selfdata  OpenChaoJi_evcc_hal_selfcheck_get_result(OpenChaoJi_hal_handle hal_handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_selfdata data = {0};
    return data;
}

/*
 * 功能  充电阶段-绝缘启动接口
 * 参数  context: 句柄
 * 参数  voltage: 绝缘电压值
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_imd_request_start(OpenChaoJi_hal_handle hal_handle, float voltage)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  充电阶段-绝缘停止接口
 * 参数  context: 句柄
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_imd_request_stop(OpenChaoJi_hal_handle hal_handle)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  充电阶段-绝缘结果获取
 * 参数  context: 句柄
 * 参数  rp_value: 正对地阻值存储地址
 * 参数  rn_value: 负对地阻值存储地址
 * 返回  -1: ERR   0:OK  1:Checking
 */
int OpenChaoJi_evcc_hal_imd_get_result(OpenChaoJi_hal_handle hal_handle,
                                       float *rp_value, float *rn_value)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  泄放启动
 * 参数  context: 句柄
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_vent_request_start(OpenChaoJi_hal_handle hal_handle)
{
    HAL_DEBUG_LINE
    return 0;
}


/*
 * 功能  泄放停止
 * 参数  context: 句柄
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_vent_request_stop(OpenChaoJi_hal_handle hal_handle)
{
    HAL_DEBUG_LINE
    return 0;
}

#endif


/*
 * 功能  电压电流采样值获取
 * 参数  context: 句柄
 * 参数  samp_value: 采样值存储地址
 * 返回  0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_sampling_value(OpenChaoJi_hal_handle handle,
                                       struct OpenChaoJi_evcc_hal_samp *samp_value)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    evcc_hal_battery_service(info);

    samp_value->voltage_in = evcc_hal_battery_get_voltage(&info->battery);
    if (info->pilot_sync_status.evcc_dc)
    {
        samp_value->voltage_out = samp_value->voltage_in;
    }
    else
    {
        if (info->pilot_sync_status.secc_dc)
        {
            samp_value->voltage_out = 0; // TODO: 此时无法知道外侧电压, 暂时置为0
        }
        else
        {
            samp_value->voltage_out = 0;
        }
    }
    if (samp_value->voltage_in == 0)
    {
        samp_value->current = 0;
    }
    else
    {
        samp_value->current = evcc_hal_battery_get_power(info) * 1000 / samp_value->voltage_in ;     // 0.01kW / 0.1V
    }

    return 0;
}


/**
 * @brief  (A/B类系统)电池投入
 * @param  OpenChaoJi_hal_handle: 句柄
 */
void OpenChaoJi_evcc_hal_battery_prepare(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return;
    }

    evcc_hal_battery_start(&info->battery);

    return;
}

/**
 * @brief  (A/B类系统)判断电池是否投入成功
 * @param  OpenChaoJi_hal_handle: 句柄
 */
bool OpenChaoJi_evcc_hal_battery_is_ready(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return false;
    }

    return info->battery.start;
}

/******************************获取车辆/电池信息******************************/

/**
 * @brief  获取车辆端绝缘监测允许总电压
 * @param  handle: 句柄
 * @return 车辆端绝缘监测允许总电压, 0.1V/位, 0V偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_imd_request_voltage(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.voltage_max;
}

/**
 * @brief  获取电池类型
 * @param  handle: 句柄
 * @return 电池类型: 01H:铅酸电池, 02H:镍氢电池, 03H:磷酸铁锂电池,
 *                  04H:锰酸锂电池, 05H:钴酸锂电池, 06H:三元材料电池,
 *                  07H:聚合物锂离子电池, 08H:钛酸锂电池, FFH:其他电池
 */
unsigned char OpenChaoJi_evcc_hal_get_batt_type(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 0x06;
}

/**
 * @brief  获取动力蓄电池额定容量
 * @param  handle: 句柄
 * @return 动力蓄电池额定容量, 0.1Ah/位, 0Ah偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_rated_capacity(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.capacity_max * 1000 / info->battery.voltage_max;
}

/**
 * @brief  获取动力蓄电池额定总电压
 * @param  handle: 句柄
 * @return 动力蓄电池额定总电压, 0.1V/位, 0V偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_rated_voltage(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.voltage_max;
}

/**
 * @brief  获取电池生产厂商名称（数组）
 * @param  handle: 句柄
 * @param  batt_factory: 电池生产厂商名称, 4字节, 标准ASCII码, 低字节在前
 * @return void
 */
void OpenChaoJi_evcc_hal_get_batt_factory(OpenChaoJi_hal_handle handle, unsigned char *batt_factory)
{
    HAL_DEBUG_LINE
    strcpy((char *)batt_factory, "CJ");
    return;
}

/**
 * @brief  获取电池组序号（数组）
 * @param  handle: 句柄
 * @param  batt_sn: 电池组序号, 4字节, 厂商自行定义
 * @return void
 */
void OpenChaoJi_evcc_hal_get_batt_sn(OpenChaoJi_hal_handle handle, unsigned char *batt_sn)
{
    HAL_DEBUG_LINE
    char tmp[] = {0x01,0x02,0x03,0x04};
    memcpy(batt_sn, tmp, 4);
    return;
}

/**
 * @brief  获取电池组生产日期
 * @param  handle: 句柄
 * @return 电池组生产日期
 */
struct OpenChaoJi_evcc_hal_batt_date OpenChaoJi_evcc_hal_get_batt_date(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_batt_date temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.year = 2025;
    temp.month = 1;
    temp.day = 20;
    return temp;
}

/**
 * @brief  获取电池组充电次数
 * @param  handle: 句柄
 * @return 电池组充电次数, 1次/位, 0次偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_charge_cycles(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 30;
}

/**
 * @brief  获取电池组产权标识
 * @param  handle: 句柄
 * @return 电池组产权标识, 0:租赁, 1:车自有
 */
unsigned char OpenChaoJi_evcc_hal_get_batt_property(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 0;
}

/**
 * @brief  获取扩展车辆识别码（数组）
 * @param  handle: 句柄
 * @param  evin: 扩展车辆识别码, 17字节, 扩展ASCII码, 低字节在前
 * @return void
 */
void OpenChaoJi_evcc_hal_get_evin(OpenChaoJi_hal_handle handle, unsigned char *evin)
{
    HAL_DEBUG_LINE
    char tmp[] = "LN123456789ABCDEF";
    memcpy(evin, tmp, 17);
    return;
}

/**
 * @brief  获取单体蓄电池最高允许充电电压
 * @param  handle: 句柄
 * @return 单体蓄电池最高允许充电电压, 0.01V/位, 0V偏移量, 0-24V
 */
unsigned int OpenChaoJi_evcc_hal_get_allow_cellvolt(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 1200;
}

/**
 * @brief  获取动力蓄电池最高允许充电总电压
 * @param  handle: 句柄
 * @return 最高允许充电总电压, 0.1V/位, 0V偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_allow_voltage(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.voltage_max;
}

/**
 * @brief  获取动力蓄电池最高允许充电电流
 * @param  handle: 句柄
 * @return 最高允许充电电流, 0.1A/位, 0A偏移量, 0-400A
 */
unsigned int OpenChaoJi_evcc_hal_get_allow_current(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 2400;
}

/**
 * @brief  获取动力蓄电池标称总能量
 * @param  handle: 句柄
 * @return 动力蓄电池标称总能量, 0.1kWh/位, 0kWh偏移量, 0-1000kWh
 */
unsigned int OpenChaoJi_evcc_hal_get_rated_energy(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.capacity_max / 100;
}

/**
 * @brief  获取单体蓄电池最高允许温度
 * @param  handle: 句柄
 * @return 单体蓄电池最高允许充电温度, 1℃/位, 0℃偏移量, -50℃~200℃
 */
int OpenChaoJi_evcc_hal_get_allow_tempera(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 70;
}

/**
 * @brief  获取整车荷电状态(当前电池SOC)
 * @param  handle: 句柄
 * @return 整车荷电状态, 0.1%/位, 0偏移量, 0-100%
 */
unsigned int OpenChaoJi_evcc_hal_get_batt_soc(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.soc;
}

/**
 * @brief  获取车辆准备就绪状态
 * @param  handle: 句柄
 * @return 车辆准备就绪状态, 0x00:车辆未做好充电准备, 0xAA:车辆完成充电准备
 */
unsigned char OpenChaoJi_evcc_hal_get_bms_ready(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 0xAA;
}

/**
 * @brief  获取车辆接口充电电压需求值
 * @param  handle: 句柄
 * @return 车辆接口充电电压需求值, 0.1V/位, 0V偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_target_voltage(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.voltage_max;
}

/**
 * @brief  获取车辆接口充电电流需求值
 * @param  handle: 句柄
 * @return 车辆接口充电电流需求值, 0.1A/位, 0A偏移量, 0-400A
 */
unsigned int OpenChaoJi_evcc_hal_get_target_current(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 1200;
}

/**
 * @brief  获取动力蓄电池充电模式需求值
 * @param  handle: 句柄
 * @return 动力蓄电池充电模式需求, 0x01:恒压充电, 0x02:恒流充电
 */
unsigned char OpenChaoJi_evcc_hal_get_charge_mode(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 0x02;
}

/**
 * @brief  获取车辆接口当前电压测量值
 * @param  handle: 句柄
 * @return 车辆接口当前电压测量值, 0.1V/位, 0V偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_measured_voltage(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE

    // struct OpenChaoJi_evcc_hal_samp samp_value;
    // int rtn =  OpenChaoJi_evcc_hal_sampling_value(handle, &samp_value);
    // if (rtn != 0)
    // {
    //     return 0;
    // }

    // return samp_value.voltage_out;

    struct evcc_hal_Info * info = evcc_hal_handle2info(handle);
    if (info == NULL)
    {
        LOG_ALERT("Invalid hal_handle %08X", handle);
        return 0;
    }

    return info->battery.voltage_max - 1000 + info->battery.soc;
}

/**
 * @brief  获取车辆接口当前电流测量值
 * @param  handle: 句柄
 * @return 车辆接口当前电流测量值, 0.1A/位, 0A偏移量, 0-400A
 */
unsigned int OpenChaoJi_evcc_hal_get_measured_current(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 100;
}

/**
 * @brief  获取估算剩余充电时间
 * @param  handle: 句柄
 * @return 估算剩余充电时间, 1min/位, 0min偏移量
 */
unsigned int OpenChaoJi_evcc_hal_get_expected_time(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 120;
}

/**
 * @brief  获取单体蓄电池最高电压检测点信息
 * @param  handle: 句柄
 * @return 单体蓄电池最高电压检测点信息
 */
struct OpenChaoJi_evcc_hal_batt_cellvolt OpenChaoJi_evcc_hal_get_max_cellvolt(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_batt_cellvolt temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.id = 256;
    temp.group = 15;
    temp.voltage = 450;
    return temp;
}

/**
 * @brief  获取单体蓄电池最低电压检测点信息
 * @param  handle: 句柄
 * @return 单体蓄电池最低电压检测点信息
 */
struct OpenChaoJi_evcc_hal_batt_cellvolt OpenChaoJi_evcc_hal_get_min_cellvolt(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_batt_cellvolt temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.id = 1;
    temp.group = 0;
    temp.voltage = 200;
    return temp;
}

/**
 * @brief  获取电池最高温度检测点信息
 * @param  handle: 句柄
 * @return 电池最高温度检测点信息
 */
struct OpenChaoJi_evcc_hal_batt_tempera OpenChaoJi_evcc_hal_get_max_tempera(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_batt_tempera temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.id = 128;
    temp.tempera = 200;
    return temp;
}

/**
 * @brief  获取电池最低温度检测点信息
 * @param  handle: 句柄
 * @return 电池最低温度检测点信息
 */
struct OpenChaoJi_evcc_hal_batt_tempera OpenChaoJi_evcc_hal_get_min_tempera(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    struct OpenChaoJi_evcc_hal_batt_tempera temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.id = 1;
    temp.tempera = -50;
    return temp;
}

/**
 * @brief  获取动力蓄电池工作状态
 * @param  handle: 句柄
 * @return 动力蓄电池工作状态
 */
union OpenChaoJi_evcc_hal_batt_state OpenChaoJi_evcc_hal_get_batt_state(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    union OpenChaoJi_evcc_hal_batt_state temp;
    memset(&temp, 0x00, sizeof(temp));
    temp.bits.charge_enable = 1;
    return temp;
}

/**
 * @brief  获取单体蓄电池电压检测点数量
 * @param  handle: 句柄
 * @return 单体蓄电池电压检测点数量, 1/位, 0偏移量, 1-256
 */
unsigned int OpenChaoJi_evcc_hal_get_cellvolt_num(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 256;
}

/**
 * @brief  获取动力蓄电池温度检测点数量
 * @param  handle: 句柄
 * @return 单体蓄电池电压检测点数量, 1/位, 0偏移量, 1-128
 */
unsigned int OpenChaoJi_evcc_hal_get_tempera_num(OpenChaoJi_hal_handle handle)
{
    HAL_DEBUG_LINE
    return 128;
}

/**
 * @brief  获取单体蓄电池电压（数组, 按检测点编号顺序依次排列）
 * @param  handle: 句柄
 * @param  group: 单体蓄电池分组号, 1/位, 0偏移量, 0-15
 * @param  cellvolt: 单体蓄电池电压值, 0.01V/位, 0V偏移量, 0-24V
 * @return void
 */
void OpenChaoJi_evcc_hal_get_cellvolt(OpenChaoJi_hal_handle handle, unsigned char *group, unsigned int *cellvolt)
{
    HAL_DEBUG_LINE
    for (int i=0; i<256; i++)
    {
        group[i] = i % 16;
        cellvolt[i] = 200 + (i * 2500 / 255) * 250 / 2500;
    }
    return;
}

/**
 * @brief  获取动力蓄电池温度（数组, 按检测点编号顺序依次排列）
 * @param  handle: 句柄
 * @param  tempera: 动力蓄电池温度值, 1℃/位, 0℃偏移量, -50℃~200℃
 * @return void
 */
void OpenChaoJi_evcc_hal_get_tempera(OpenChaoJi_hal_handle handle, int *tempera)
{
    HAL_DEBUG_LINE
    for (int i=0; i<128; i++)
        tempera[i] = -50 + (i * 2500 / 127) * 250 / 2500;
    return;
}

/******************************更新车辆/电池信息******************************/

/**
 * @brief  更新车辆当前时间
 * @param  handle: 句柄
 * @param  time: 同步时间
 * @return 0:OK  -1:ERR
 */
int OpenChaoJi_evcc_hal_set_time(OpenChaoJi_hal_handle handle, time_t time)
{
    HAL_DEBUG_LINE
    return 0;
}

